mod(['//cdn.bootcss.com/codemirror/5.27.2/codemirror.min.js','//cdn.bootcss.com/ramda/0.24.1/ramda.min.js'],function(){
  imptcss('//cdn.bootcss.com/codemirror/5.27.2/codemirror.min.css')
  imptjs('//cdn.bootcss.com/codemirror/5.27.2/mode/javascript/javascript.min.js').then(main)

  function b64EncodeUnicode(str) {
    // first we use encodeURIComponent to get percent-encoded UTF-8,
    // then we convert the percent encodings into raw bytes which
    // can be fed into btoa.
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
      function toSolidBytes(match, p1) {
        return String.fromCharCode('0x' + p1)
    }));
  }
  
  function b64DecodeUnicode(str) {
    // Going backwards: from bytestream, to percent-encoding, to original string.
    return decodeURIComponent(atob(str).split('').map(function(c) {
      return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
  }
  var STATE_BEFORE_EXECUTE = []
  function emitState(xs,arg){
    try{
      R.forEach(R.apply(R.__,arg),xs)
    }catch(e){
      void null
    }
  }
  function changeProxy(edit,bizfn){
    var time = null
    return function(){
      clearTimeout(time)
      time = setTimeout(fn,1000)
    }
    function fn(){
      bizfn(edit.getValue())
    }
  }
  function delayCall(ms){
    var time = null
    return function(fn){
      clearTimeout(time)
      time = setTimeout(fn,ms)
    }
  }
  function execute(code){
    var ncode = code.trim().split('\n')
    ncode[ncode.length-1] = 'return ' + ncode[ncode.length-1]
    emitState(STATE_BEFORE_EXECUTE,[code])
    ncode = ncode.join('\n')
    delete window._fn_diqye_
    var r = null
    var logs = []
    var delay500 = delayCall(500)
    try{
      window._fn_diqye_ = new Function('_,log',ncode)
      r = _fn_diqye_(R,function(o,a,b,c){
        if(c !== undefined){
          logs.push('('+[R.toString(o),R.toString(a),R.toString(b),R.toString(c)].join(' , ')+')')
        }else if(b !== undefined){
          logs.push('('+[R.toString(o),R.toString(a),R.toString(b)].join(' , ')+')')
        }else if(a !== undefined){
          logs.push('('+[R.toString(o),R.toString(a)].join(' , ')+')')
        }else{
          logs.push(R.toString(o))
        }
        delay500(resultfn)
      })
    }catch(e){
      r = e
    }
    function resultfn(){
      if(logs.length ==0){
        document.getElementById('result').innerText = R.toString(r)
      }else{
        document.getElementById('result').innerText = R.toString(r) +'\n\n log:\n' + logs.join('\n')
      }
    }
    delay500(resultfn)
    
  }
  function findIdx(xs){
    for (var i = xs.length - 1; i >= 0; i--) {
      if(xs[i].trim() != '') return i
      else void null
    }
  }
  function main(){
    var myCodeMirror = CodeMirror(function(el){
      document.getElementById('code').appendChild(el)
    },{
      lineNumbers:true,
      value: "'I am diqye'\n",
      mode:'javascript',
      tabSize:2
    })
    myCodeMirror.setSize('100%','100%')
    myCodeMirror.on('change',changeProxy(myCodeMirror,execute))
    if(location.hash == ""){
      void null
    }else{
      myCodeMirror.setValue(b64DecodeUnicode(location.hash.slice(1)))
    }
    execute(myCodeMirror.getValue())
    STATE_BEFORE_EXECUTE.push(function(code){
      location.hash = b64EncodeUnicode(code)
    })
  }
  
})
